#! /bin/bash
# chkconfig: 2345 55 25
# Description: Startup script for Ngrok on Debian. Place in /etc/init.d and
# run 'update-rc.d -f ngrokd defaults', or use the appropriate command on your
# distro. For CentOS/Redhat run: 'chkconfig --add ngrokd'
#=======================================================
#   System Required:  CentOS/Debian/Ubuntu (32bit/64bit)
#   Description:  Manager for Ngrok, Written by Clang
#   Author: Clang <admin@clangcn.com>
#   Intro:  http://clangcn.com
#=======================================================
### BEGIN INIT INFO
# Provides:          ngrok
# Required-Start:    $all
# Required-Stop:     $all
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: starts the ngrok
# Description:       starts ngrok using start-stop
### END INIT INFO
# Source function library
if [ -f /etc/rc.d/init.d/functions ]; then
    . /etc/rc.d/init.d/functions
# Check that networking is up.
    [ ${NETWORKING} ="yes" ] || exit 0
fi
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
ProgramName="Ngrok"
ProGramInstallPath="/usr/local/ngrok"
ProgramPath="/usr/local/ngrok/bin"
NAME=ngrokd
BIN=${ProgramPath}/${NAME}
CONFIGFILE=${ProGramInstallPath}/.ngrok_config.sh
LOGFILE=${ProGramInstallPath}/ngrok.log
SCRIPTNAME=/etc/init.d/${NAME}
PID_DIR=/var/run
PID_FILE=${PID_DIR}/ngrok_clang.pid
version="8.2"
manage_port="4446"
RET_VAL=0

[ -x $BIN ] || exit 0
if [ ! -d $PID_DIR ]; then
    mkdir -p $PID_DIR
    if [ $? -ne 0 ]; then
        echo "Creating PID directory $PID_DIR failed"
        exit 1
    fi
fi
fun_clangcn()
{
    echo ""
    echo "+----------------------------------------------+"
    echo "|      Manager for Ngrok, Written by Clang     |"
    echo "+----------------------------------------------+"
    echo "|            Intro: http://clang.cn/           |"
    echo "+----------------------------------------------+"
    echo ""
}
fun_check_run() {
    PID=`ps -ef | grep -v grep | grep -i "${BIN}" | awk '{print $2}'`
    if [ ! -z $PID ]; then
        return 0
    else
        return 1
    fi
}

fun_load_config(){    
    if [ ! -r ${CONFIGFILE} ]; then
        echo "config file ${CONFIGFILE} not found"
        return 1
    else
        . ${CONFIGFILE}
        log_level=""
        [ -n "${loglevel}" ] && log_level=" -log-level=\"${loglevel}\""
        cd ${ProGramInstallPath}
    fi
}
fun_check_port(){
    fun_load_config
    strHttpPort=""
    strHttpsPort=""
    strRemotePort=""
    strManPort=""
    strHttpPort=`netstat -ntl | grep "\b:${http_port}\b"`
    strHttpsPort=`netstat -ntl | grep "\b:${https_port}\b"`
    strRemotePort=`netstat -ntl | grep "\b:${remote_port}\b"`
    strManagePort=`netstat -ntl | grep "\b:${manage_port}\b"`
    if [ -n "${strHttpPort}" ] || [ -n "${strHttpsPort}" ] || [ -n "${strRemotePort}" ] || [ -n "${strManagePort}" ]; then
        [ -n "${strHttpPort}" ] && str_http_port="\"${http_port}\" "
        [ -n "${strHttpsPort}" ] && str_https_port="\"${https_port}\" "
        [ -n "${strRemotePort}" ] && str_remote_port="\"${remote_port}\" "
        [ -n "${strManagePort}" ] && str_manage_port="\"${manage_port}\" "
        echo ""
        echo "Error: Port ${str_http_port}${str_https_port}${str_remote_port}${str_manage_port}is used,view relevant port:"
        [ -n "${strHttpPort}" ] && netstat -ntlp | grep "\b:${http_port}\b"
        [ -n "${strHttpsPort}" ] && netstat -ntlp | grep "\b:${https_port}\b"
        [ -n "${strRemotePort}" ] && netstat -ntlp | grep "\b:${remote_port}\b"
        [ -n "${strManagePort}" ] && netstat -ntlp | grep "\b:${manage_port}\b"
        return 1
    fi
}
fun_randstr(){
  index=0
  strRandomPass=""
  for i in {a..z}; do arr[index]=$i; index=`expr ${index} + 1`; done
  for i in {A..Z}; do arr[index]=$i; index=`expr ${index} + 1`; done
  for i in {0..9}; do arr[index]=$i; index=`expr ${index} + 1`; done
  for i in {1..16}; do strRandomPass="$strRandomPass${arr[$RANDOM%$index]}"; done
  echo $strRandomPass
}
fun_start()
{
    if [ "${arg1}" = "start" ]; then
      fun_clangcn
    fi
    if fun_check_run; then
        echo "${NAME} (pid $PID) already running."
        return 0
    fi
    echo -n "Starting ${ProgramName}: "
    fun_check_port
    fun_load_config
    ${BIN} -domain="$dns" -httpAddr=":$http_port" -httpsAddr=":$https_port" -pass="$pass" -tlsCrt="$srtCRT" -tlsKey="$strKey" -tunnelAddr=":$remote_port"${log_level} > ${LOGFILE} 2>&1 &
    RETVAL=$?
    PID=$(ps -ef | grep -v grep | grep -i ${BIN} | awk '{print $2}')
    if [ -f /etc/rc.d/init.d/functions ]; then
        [ $RETVAL -eq 0 ] && success
    else
        if fun_check_run; then
            echo "    [ok]"
        else
            echo "    [FAILED]"
            RETVAL=1
        fi
    fi
}

fun_stop(){
    if [ "${arg1}" = "stop" ] || [ "${arg1}" = "restart" ]; then
      fun_clangcn
    fi
    if fun_check_run; then
        echo -n $"Stopping ${ProgramName}: "
        if [ -f /etc/rc.d/init.d/functions ]; then
            killproc -p $PID_FILE >/dev/null 2>&1
        else
            if fun_check_run; then
                kill -9 $PID >/dev/null 2>&1
                echo "    [ok]"
            else
                echo "    [FAILED]"
                RETVAL=1
            fi
        fi
        RETVAL=$?
        [ $RETVAL -eq 0 ]
        rm -f $PID_FILE
    else
        echo "${ProgramName} is not running."
    fi
}

fun_restart(){
    fun_stop
    fun_start
}
fun_status(){
    fun_check_run
    case $? in
        0)
        echo "$NAME (pid $PID) is running..."
        ;;
        1|2)
        echo "$NAME is stopped"
        RET_VAL=1
        ;;
    esac
}
checkos(){
    if grep -Eqi "CentOS" /etc/issue || grep -Eq "CentOS" /etc/*-release; then
        OS=CentOS
    elif grep -Eqi "Debian" /etc/issue || grep -Eq "Debian" /etc/*-release; then
        OS=Debian
    elif grep -Eqi "Ubuntu" /etc/issue || grep -Eq "Ubuntu" /etc/*-release; then
        OS=Ubuntu
    else
        echo "Not support OS, Please reinstall OS and retry!"
        exit 1
    fi
}
fun_config(){
    if [ -s ${CONFIGFILE} ]; then
        vi ${CONFIGFILE}
    else
        echo "${ProgramName} configuration file not found!"
    fi
}
fun_set_ngrok_username(){
    userName=""
    read -p "Please input UserName for Ngrok(e.g.:ZhangSan):" userName
    check_ngrok_username
}
fun_set_ngrok_subdomain(){
    # Set ngrok pass
    subdomain=""
    ddns=""
    dns=""
    echo "Please input subdomain for Ngrok(e.g.:dns1 dns2 dns3 dns4 dns5):"
    read -p "(subdomain number max five:):" subdomain
    check_ngrok_subdomain
}
fun_set_ngrok_authId(){
    strPass=`fun_randstr`
    echo "Please input the password (more than 8) of Ngrok authId:"
    read -p "(Default password: ${strPass}):" strPassword
    if [ "$strPassword" = "" ]; then
        strPassword=$strPass
    fi
    check_ngrok_authId
}

check_ngrok_username(){
    # check ngrok userName
    if [ "$userName" = "" ]; then
        echo "Your input is empty,please input again..."
        fun_set_ngrok_username
    else
        echo "Your username: ${userName}"
        fun_set_ngrok_subdomain
    fi
}
check_ngrok_subdomain(){
    # check ngrok subdomain
    if [ "$subdomain" = "" ]; then
        echo "Your input is empty, please input again."
        fun_set_ngrok_subdomain
    else
        fun_load_config
        ddns=(${subdomain})
        if [ "$SingleUser" = "y" ] || [ "$SingleUser" = "1" ]; then
            [ -n "${ddns[0]}" ] && subdns=\"${ddns[0]}\"
            [ -n "${ddns[1]}" ] && subdns=\"${ddns[0]}\",\"${ddns[1]}\"
            [ -n "${ddns[2]}" ] && subdns=\"${ddns[0]}\",\"${ddns[1]}\",\"${ddns[2]}\"
            [ -n "${ddns[3]}" ] && subdns=\"${ddns[0]}\",\"${ddns[1]}\",\"${ddns[2]}\",\"${ddns[3]}\"
            [ -n "${ddns[4]}" ] && subdns=\"${ddns[0]}\",\"${ddns[1]}\",\"${ddns[2]}\",\"${ddns[3]}\",\"${ddns[4]}\"
            [ -n "${ddns[0]}" ] && FQDN=\"${ddns[0]}.${dns}\"
            [ -n "${ddns[1]}" ] && FQDN=\"${ddns[0]}.${dns}\",\"${ddns[1]}.${dns}\"
            [ -n "${ddns[2]}" ] && FQDN=\"${ddns[0]}.${dns}\",\"${ddns[1]}.${dns}\",\"${ddns[2]}.${dns}\"
            [ -n "${ddns[3]}" ] && FQDN=\"${ddns[0]}.${dns}\",\"${ddns[1]}.${dns}\",\"${ddns[2]}.${dns}\",\"${ddns[3]}.${dns}\"
            [ -n "${ddns[4]}" ] && FQDN=\"${ddns[0]}.${dns}\",\"${ddns[1]}.${dns}\",\"${ddns[2]}.${dns}\",\"${ddns[3]}.${dns}\",\"${ddns[4]}.${dns}\"
        else
            [ -n "${ddns[0]}" ] && subdns=\"${ddns[0]}.${userName}\"
            [ -n "${ddns[1]}" ] && subdns=\"${ddns[0]}.${userName}\",\"${ddns[1]}.${userName}\"
            [ -n "${ddns[2]}" ] && subdns=\"${ddns[0]}.${userName}\",\"${ddns[1]}.${userName}\",\"${ddns[2]}.${userName}\"
            [ -n "${ddns[3]}" ] && subdns=\"${ddns[0]}.${userName}\",\"${ddns[1]}.${userName}\",\"${ddns[2]}.${userName}\",\"${ddns[3]}.${userName}\"
            [ -n "${ddns[4]}" ] && subdns=\"${ddns[0]}.${userName}\",\"${ddns[1]}.${userName}\",\"${ddns[2]}.${userName}\",\"${ddns[3]}.${userName}\",\"${ddns[4]}.${userName}\"
            [ -n "${ddns[0]}" ] && FQDN=\"${ddns[0]}.${userName}.${dns}\"
            [ -n "${ddns[1]}" ] && FQDN=\"${ddns[0]}.${userName}.${dns}\",\"${ddns[1]}.${userName}.${dns}\"
            [ -n "${ddns[2]}" ] && FQDN=\"${ddns[0]}.${userName}.${dns}\",\"${ddns[1]}.${userName}.${dns}\",\"${ddns[2]}.${userName}.${dns}\"
            [ -n "${ddns[3]}" ] && FQDN=\"${ddns[0]}.${userName}.${dns}\",\"${ddns[1]}.${userName}.${dns}\",\"${ddns[2]}.${userName}.${dns}\",\"${ddns[3]}.${userName}.${dns}\"
            [ -n "${ddns[4]}" ] && FQDN=\"${ddns[0]}.${userName}.${dns}\",\"${ddns[1]}.${userName}.${dns}\",\"${ddns[2]}.${userName}.${dns}\",\"${ddns[3]}.${userName}.${dns}\",\"${ddns[4]}.${userName}.${dns}\"
        fi
        echo "Your subdomain: ${subdns}"
        fun_set_ngrok_authId
    fi
}
check_ngrok_authId(){
    # check ngrok authId
    if [ "${strPassword}" = "" ]; then
        echo "Your input is empty, please input again..."
        fun_set_ngrok_authId
    else
        echo "Your authId: ${strPassword}"
        fun_adduser_command
    fi
}
fun_adduser_command(){
    fun_load_config
    clear
    fun_clangcn
    echo  curl -H \"Content-Type: application/json\" -H \"Auth:${pass}\" -X POST -d \''{'\"userId\":\"${strPassword}\",\"authId\":\"${userName}\",\"dns\":[${subdns}]'}'\' http://localhost:${manage_port}/adduser >${ProGramInstallPath}/.ngrok_adduser.sh
    chmod +x ${ProGramInstallPath}/.ngrok_adduser.sh
    . ${ProGramInstallPath}/.ngrok_adduser.sh
    rm -f ${ProGramInstallPath}/.ngrok_adduser.sh
    echo ""
    echo "User list :"
    curl -H "Content-Type: application/json" -H "Auth:${pass}" -X GET http://localhost:${manage_port}/info
    echo "============================================================="
    echo "Server: ${dns}"
    echo "Server  ${remote_port}"
    echo "userId: ${userName}"
    echo "authId: ${strPassword}"
    echo "Subdomain: ${subdns}"
    echo "Your FQDN: ${FQDN}"
    echo "============================================================="
}
fun_adduser(){
    if fun_check_run; then
        fun_load_config
        fun_set_ngrok_username
    else
        echo "${ProgramName} is not running."
    fi
}
fun_deluser(){
    if [ -z "${1}" ]; then
        strWantdeluser=""
        fun_userlist
        echo ""
        read -p "Please input del username you want:" strWantdeluser
        if [ "${strWantdeluser}" = "" ]; then
            echo "Error: You must input username!!"
            exit 1
        else
            deluser_Confirm_clang "${strWantdeluser}"
        fi
    else
        deluser_Confirm_clang "${1}"
    fi
}
deluser_Confirm_clang(){
    if [ -z "${1}" ]; then
        echo "Error: You must input username!!"
        exit 1
    else
        strDelUser="${1}"
        echo "You want del ${strDelUser}!"
        read -p "(if you want please input: y,Default [no]):" strConfirmDel
        case "$strConfirmDel" in
        y|Y|Yes|YES|yes|yES|yEs|YeS|yeS)
        echo ""
        strConfirmDel="y"
        ;;
        n|N|No|NO|no|nO)
        echo ""
        strConfirmDel="n"
        ;;
        *)
        echo ""
        strConfirmDel="n"
        esac
        if [ $strConfirmDel = "y" ]; then
            if [ -s "${ProGramInstallPath}/users/ng/ro/ngrok:${strDelUser}" ]; then
                rm -f ${ProGramInstallPath}/users/ng/ro/ngrok:${strDelUser}
                echo "Delete user ${strDelUser}　ok! Restart ${NAME}..."
                fun_restart
            else
                echo ""
                echo "Error: user ${strDelUser} not found!"
            fi
        else
            echo "you cancel!"
        fi
    fi
}
fun_userlist(){
    fun_clangcn
    echo "Ngrok user list:"
    ls ${ProGramInstallPath}/users/ng/ro/ |cut -d ':' -f 2
}
fun_info(){
    fun_clangcn
    if fun_check_run; then
        fun_load_config
        curl -H "Content-Type: application/json" -H "Auth:${pass}" -X GET http://localhost:${manage_port}/info
    else
        echo "${ProgramName} is not running."
    fi
}
arg1=$1
arg2=$2
[  -z ${arg1} ]
case "${arg1}" in
    start|stop|restart|status|config|adduser|deluser|userlist|info)
        fun_${arg1} ${arg2}
    ;;
    *)
        fun_clangcn
        echo "Usage: $SCRIPTNAME {start|stop|restart|status|config|adduser|deluser|userlist|info}"
        RET_VAL=1
    ;;
esac
exit $RET_VAL
